#include "setwig.h"
#include "ui_setwig.h"
#include "globalval.h"
QJsonObject json;//构造一个空的 JSON 对象,用于进行点表下发
SetWig::SetWig(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::SetWig)
{
    ui->setupUi(this);

    connect(ui->pushButton, SIGNAL(clicked()), this, SLOT(on_publishButton_clicked()));
    connect(ui->pushButton_2, SIGNAL(clicked()), this, SLOT(on_publishButton2_clicked()));
    connect(ui->pushButton_3, SIGNAL(clicked()), this, SLOT(on_publishButton3_clicked()));
    connect(ui->pushButton_4, SIGNAL(clicked()), this, SLOT(on_publishButton4_clicked()));


    //创建udp对象
    udpSocket = new QUdpSocket(this);
    //创建tcp客户端对象
    socket = new QTcpSocket(this);
    //创建tcp文件对象
    fliesocket=new QTcpSocket(this);
    //发送广播槽函数
    connect(ui->pushButtonSearch,SIGNAL(clicked()),this,SLOT(btnSearchSlot()));
    //接收广播回复
    connect(udpSocket, SIGNAL(readyRead()), this,SLOT(udpRecvSlot()));
    //建立第一个TCP连接
    connect(ui->pushButtonLogin,SIGNAL(clicked()),this,SLOT(btnLoginSlot()));
    //接收服务器数据
    connect(socket,SIGNAL(readyRead()),this,SLOT(n1tcpReadSlot()));
    //第二个tcp发送文件
    connect(fliesocket,SIGNAL(connected()),this,SLOT(connectFileSlot()));
    // 创建定时器，每隔1秒发送心跳包
    timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this,SLOT(heartTimerSlot()));
    timer->start(1000); // 1000毫秒为间隔

}

SetWig::~SetWig()
{
    delete ui;
}

void SetWig::on_publishButton_clicked()
{
    // 创建JSON对象
    QJsonObject jsonObject;

    // 添加控制指令类型
    jsonObject["type"] = QJsonValue(3);

    // 创建数据子对象
    QJsonObject dataObject;

    // 添加数据点唯一标识和数据点键值
    dataObject["type"] = QJsonValue(0);
    dataObject["period"] = QJsonValue(5);

    // 将数据子对象添加到主对象
    jsonObject["data"] = dataObject;

    // 创建QJsonDocument并添加JSON对象
    QJsonDocument jsonDoc(jsonObject);

    // 将JSON文档序列化为字符串
    QString jsonString = jsonDoc.toJson(QJsonDocument::Compact);

    // 创建一个QMQTT::Message对象
    QMQTT::Message message;
    message.setTopic("lc"); // 设置发布的主题
    message.setPayload(jsonString.toUtf8()); // 设置消息内容，注意转换
    message.setQos(1); // 设置服务质量等级

    // 使用MqttHandler实例发布消息
    quint16 messageId = GlobalVal::mqtt->publish(message);
    qDebug() << "Message published with ID" << messageId;
}

void SetWig::on_publishButton2_clicked()
{
    // 创建JSON对象
    QJsonObject jsonObject;

    // 添加控制指令类型
    jsonObject["type"] = QJsonValue(3);

    // 创建数据子对象
    QJsonObject dataObject;

    // 添加数据点唯一标识和数据点键值
    dataObject["type"] = QJsonValue(1);
    dataObject["period"] = QJsonValue(5);

    // 将数据子对象添加到主对象
    jsonObject["data"] = dataObject;

    // 创建QJsonDocument并添加JSON对象
    QJsonDocument jsonDoc(jsonObject);

    // 将JSON文档序列化为字符串
    QString jsonString = jsonDoc.toJson(QJsonDocument::Compact);

    // 创建一个QMQTT::Message对象
    QMQTT::Message message;
    message.setTopic("lc"); // 设置发布的主题
    message.setPayload(jsonString.toUtf8()); // 设置消息内容，注意转换
    message.setQos(1); // 设置服务质量等级

    // 使用MqttHandler实例发布消息
    quint16 messageId = GlobalVal::mqtt->publish(message);
    qDebug() << "Message published with ID" << messageId;
}

void SetWig::on_publishButton3_clicked()
{
    // 创建JSON对象
    QJsonObject jsonObject;

    // 添加控制指令类型
    jsonObject["type"] = QJsonValue(3);

    // 创建数据子对象
    QJsonObject dataObject;

    // 添加数据点唯一标识和数据点键值
    dataObject["type"] = QJsonValue(2);
    dataObject["period"] = QJsonValue(5);

    // 将数据子对象添加到主对象
    jsonObject["data"] = dataObject;

    // 创建QJsonDocument并添加JSON对象
    QJsonDocument jsonDoc(jsonObject);

    // 将JSON文档序列化为字符串
    QString jsonString = jsonDoc.toJson(QJsonDocument::Compact);

    // 创建一个QMQTT::Message对象
    QMQTT::Message message;
    message.setTopic("lc"); // 设置发布的主题
    message.setPayload(jsonString.toUtf8()); // 设置消息内容，注意转换
    message.setQos(1); // 设置服务质量等级

    // 使用MqttHandler实例发布消息
    quint16 messageId = GlobalVal::mqtt->publish(message);
    qDebug() << "Message published with ID" << messageId;
}

void SetWig::on_publishButton4_clicked()
{
    // 创建JSON对象
    QJsonObject jsonObject;

    QJsonArray keys;
    keys<<1<<2<<3<<4;
    jsonObject["keys"]=keys;
    jsonObject["limit"]="all";
    jsonObject["type"]=1;

    // 创建QJsonDocument并添加JSON对象
    QJsonDocument jsonDoc(jsonObject);

    // 将JSON文档序列化为字符串
    QString jsonString = jsonDoc.toJson(QJsonDocument::Compact);

    // 创建一个QMQTT::Message对象
    QMQTT::Message message;
    message.setTopic("lc"); // 设置发布的主题
    message.setPayload(jsonString.toUtf8()); // 设置消息内容，注意转换
    message.setQos(1); // 设置服务质量等级

    // 使用MqttHandler实例发布消息
    quint16 messageId = GlobalVal::mqtt->publish(message);
    qDebug() << "Message published with ID" << messageId;
}


//进行UDP广播
void SetWig::btnSearchSlot()
{
    //绑定广播地址
    QHostAddress broadcastAddress(UDPIP);

    QByteArray datagram = "coffee"; // 你想要广播的消息

    if (udpSocket->writeDatagram(datagram, datagram.size(), broadcastAddress,7655))
    { // 7655是端口号
        // 消息成功发送
        qDebug()<<"广播成功";//将数据报大小的数据发送到端口端口的主机地址地址。返回成功时发送的字节数,字节数>0成功
    } else {
        // 消息发送失败
        qDebug()<<"广播失败";
    }
}
//接收服务器数据
void SetWig::n1tcpReadSlot()
{
    if (socket->state() == QAbstractSocket::ConnectedState)
    {
        // 继续进行发送数据等操作，比如调用waitForBytesWritten() 等
    } else
    {
        qDebug() << "套接字未连接，无法发送数据";
    }
    QByteArray buffer = socket->readAll();
    // QByteArray → QString
    QString text(buffer);
    if(text=="yes")
    {
        QMessageBox::information(this,"信息","tcp连接成功");
        json["type"] = 1;//将json格式 "type" 字段的值设置为 1。
        // 创建JSON文档
        QJsonDocument jsonDoc(json);
        // 将JSON文档转换为字节数组
        QByteArray jsonData = jsonDoc.toJson();
        // 发送JSON数据
        socket->write(jsonData);

        //建立第二个TCP连接
        fliesocket->connectToHost(tcpip,5567);
    }
    else if(text == "living")
    {
        qDebug()<<"process living";
    }
    else
        qDebug()<<"tcp连接失败";
}
//建立TCP连接
void SetWig::btnLoginSlot()
{
    //建立第一个TCP连接
    socket->connectToHost(tcpip,7655);
}
//接收广播回复
void SetWig::udpRecvSlot()
{
    while (udpSocket->hasPendingDatagrams()) //如果至少有一个数据报等待读取，则返回 true；否则返回 false。
    {
        QByteArray datagram;
        datagram.resize(udpSocket->pendingDatagramSize());//resize 调整缓冲区大小以适应接收到的数据量
        //pendingDatagramSize返回第一个挂起的 UDP 数据报的大小。如果没有可用的数据报，此函数返回 - 1。
        QHostAddress sender;//发送者的ip地址

        quint16 senderPort;//发送者端口号
        udpSocket->readDatagram(datagram.data(), datagram.size(), &sender, &senderPort);//读取接收到的数据放到data中
        tcpip = sender.toString();//获取服务器地址
        // 读取资源文件内容到 QByteArray
        QFile file(":/new/prefix1/node.json"); // 读取Qt资源中的JSON文件
        if (file.open(QIODevice::ReadOnly))
        {
            QByteArray data = file.readAll();
            file.close();

            // 解析 JSON 数据
            QJsonDocument doc = QJsonDocument::fromJson(data);
            if (doc.isObject())
            {
                QJsonObject json = doc.object();

                // 修改 mb_dev 的 addr 字段
                QJsonObject mbDevObj = json["mb_dev"].toObject();
                mbDevObj["addr"] = sender.toString(); // 修改 addr
                json["mb_dev"] = mbDevObj;

                // 修改 mqtt_server 的 addr 字段
                QJsonObject mqttServerObj = json["mqtt_server"].toObject();
                mqttServerObj["addr"] = sender.toString(); // 修改 addr
                json["mqtt_server"] = mqttServerObj;

                // 将修改后的 JSON 数据转换为字节数组，并且保持字段顺序
                // 使用 QJsonArray 来保持顺序
                QList<QPair<QString, QJsonValue> > orderedList;

                // 遍历 JSON 对象并将键值对按顺序添加到 orderedList 中
                for (auto it = json.begin(); it != json.end(); ++it) {
                    orderedList.append(qMakePair(it.key(), it.value()));
                }

                // 将列表重新转化为 QJsonObject 保持顺序
                QJsonObject orderedJson;
                for (const QPair<QString, QJsonValue>& pair : orderedList) {
                    orderedJson.insert(pair.first, pair.second);
                }

                // 将有序的 JSON 数据转换为字节数组
                QJsonDocument saveDoc(orderedJson);
                QByteArray saveData = saveDoc.toJson(QJsonDocument::Indented); // 使用缩进格式更易读

                // 获取临时文件路径
                QString tempFilePath = QDir::tempPath() + "/node_modified.json"; // 保存到临时路径

                // 保存修改后的 JSON 数据到文件（指定 UTF-8 编码）
                QFile saveFile(tempFilePath);
                if (saveFile.open(QIODevice::WriteOnly | QIODevice::Text))
                {
                    QTextStream out(&saveFile);
                    out.setCodec("UTF-8");
                    out << saveData; // 写入修改后的数据
                    saveFile.close();
                    qDebug() << "Modified JSON saved to: " << tempFilePath;
                }
            }
        }
        // 打印发送者地址和接收到的数据
        qDebug() << "Received datagram from:" << sender.toString() << datagram.data();
        ui->textBrowser->append(sender.toString());
        udpSocket->close();//关闭广播
    }
}
//发送文件
void SetWig::connectFileSlot()
{
    // 获取保存的文件路径
    QString tempFilePath = QDir::tempPath() + "/node_modified.json"; // 临时文件路径
    QFile readFile(tempFilePath);
    readFile.open(QIODevice::ReadOnly);//以只读方式读取文件
    QByteArray file;  //用于存储即将读取的文件内容。
    qint64 totalSize = readFile.size();//获取到文件的总大小
    qDebug()<<totalSize;
    file = readFile.read(totalSize);//读取文件的全部内容
    qDebug()<<file;
    fliesocket->write(file);//向设备发送文件
}
void SetWig::heartTimerSlot()
{
    // 添加其他键值对
    json["type"] = 3;
    // 创建JSON文档
    QJsonDocument jsonDoc(json);

    // 将JSON文档转换为字节数组
    QByteArray jsonData = jsonDoc.toJson();

    // 发送JSON数据
    socket->write(jsonData);

    // 等待数据发送完毕
    if (socket->waitForBytesWritten())
    {
        qDebug() << "JSON data sent successfully1";
    } else
    {
        qDebug() << "Failed to send JSON data";
    }
}
